package holdtime.xlxc.service;

import android.annotation.SuppressLint;
import android.app.Service;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCallback;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattDescriptor;
import android.bluetooth.BluetoothProfile;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.os.SystemClock;
import android.support.annotation.Nullable;
import android.util.Log;

import java.util.UUID;

import holdtime.xlxc.activities.practicedriving.AppConstants;
import holdtime.xlxc.activities.practicedriving.IsConnected;
import holdtime.xlxc.activities.practicedriving.StringPool;
import holdtime.xlxc.tools.util.ByteTool;

/**
 * Created by 徐杨 on 16/8/25.
 * 邮箱：544066591@qq.com
 */
public class BLEService extends Service {
    //    public static final UUID DATA_SERVICE = UUID.fromString("00003a06-0000-1000-8000-00805f9b34fb");
    public static final UUID NOTIFY = UUID.fromString("00002a09-0000-1000-8000-00805f9b34fb");
    public static final UUID WRITE = UUID.fromString("00002a05-0000-1000-8000-00805f9b34fb");
    public final static int MSG_PERIODFILE_SEND = 1;
    //*数据接收缓冲区大小*/
    public static final int SEND_MAX_BUFFER_SIZE = (1024);
    private static final String TAG = "XLXC";
    public static String bluetoothName = "";
    public BleServerServiceThread mBleServerServiceThread;
    BluetoothDevice device;
    private BluetoothAdapter mBluetoothAdapter;
    private BluetoothGatt mGatt;
    private BluetoothGattCharacteristic writeCharacteristic;
    private Handler handler;
    private SerBroad mSerBroad;
    //数据帧保存缓冲
    private byte[] gbtBleSendData = new byte[SEND_MAX_BUFFER_SIZE];
    private int btBleSendDataIndexW;
    private int btBleSendDataIndexR;
    private boolean btSendFlag = false;
    private BluetoothAdapter.LeScanCallback mLeScanCallback = new BluetoothAdapter.LeScanCallback() {
        @Override
        public void onLeScan(BluetoothDevice bluetoothDevice, int i, byte[] bytes) {
            Log.e(TAG, "发现设备" + bluetoothDevice.getName());
            if (bluetoothDevice.getName() != null && bluetoothDevice.getName().equals(bluetoothName)) {
                if (mBluetoothAdapter.isDiscovering()) {
                    mBluetoothAdapter.cancelDiscovery();
                }
                mBluetoothAdapter.stopLeScan(mLeScanCallback);
                device = bluetoothDevice;
                connect(device);
                Log.e(TAG, "连接设备" + bluetoothName);
            }
        }
    };
    private BluetoothGattCallback mGattCallback = new BluetoothGattCallback() {
        @Override
        public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
            Log.e(TAG, "状态:" + status + "   " + "新状态:" + newState);
            super.onConnectionStateChange(gatt, status, newState);
            if (newState == BluetoothProfile.STATE_CONNECTED) {
                sendBroad(AppConstants.MYACTION, "mTxtStatus", "连接成功");
                IsConnected.getCurrent().setHasConnected(true);
                Log.e(TAG, "单例connect 已连接");
                mBluetoothAdapter.stopLeScan(mLeScanCallback);
                SystemClock.sleep(500);
                mGatt.discoverServices();
            }
            if (newState == BluetoothProfile.STATE_DISCONNECTED) {
                gatt.close();
                sendBroad(AppConstants.MYACTION, "mTxtStatus", "连接断开");
                IsConnected.getCurrent().setHasConnected(false);
                Log.e(TAG, "单例connect 未连接");
            }
        }

        @Override
        public void onServicesDiscovered(BluetoothGatt gatt, int status) {
            super.onServicesDiscovered(gatt, status);

//            String notifyID;
//            String writeID;
//
//            writeID = String.valueOf(gatt.getServices().get(2).getCharacteristics().get(0).getUuid());
//            notifyID = String.valueOf(gatt.getServices().get(2).getCharacteristics().get(1).getUuid());
//
//            UUID NOTIFY = UUID.fromString(notifyID);
//            UUID WRITE = UUID.fromString(writeID);
//
//            readCharacteristic = gatt.getServices().get(2).getCharacteristic(NOTIFY);
//            writeCharacteristic = gatt.getServices().get(2).getCharacteristic(WRITE);
//
//            boolean b = mGatt.setCharacteristicNotification(readCharacteristic, true);
//
//            Log.e(TAG, "" + b);
//            Log.e(TAG, "onserviceDiscover");
//            if (readCharacteristic == null) {
//                Log.e(TAG, "readcharacteristic is null");
//            }

            //原始方法
//            readCharacteristic = gatt.getService(DATA_SERVICE).getCharacteristic(WRITE);
//            writeCharacteristic = gatt.getService(DATA_SERVICE).getCharacteristic(NOTIFY);
            BluetoothGattCharacteristic readCharacteristic = gatt.getServices().get(2).getCharacteristic(WRITE);
            writeCharacteristic = gatt.getServices().get(2).getCharacteristic(NOTIFY);

            boolean b = mGatt.setCharacteristicNotification(readCharacteristic, true);

            Log.e(TAG, "设置readcharacteristic" + b);
            if (readCharacteristic == null) {
                Log.e(TAG, "readcharacteristic为空");
            }
        }

        @Override
        public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
            super.onCharacteristicRead(gatt, characteristic, status);
//            Log.e(TAG, "onCharacteristicRead+ " + characteristic.getValue());
        }

        @Override
        public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
            super.onCharacteristicWrite(gatt, characteristic, status);
//            Log.e(TAG, "onCharacteristicWrite+ " + RadixUtils.bytesToHexString(characteristic.getValue()));
        }

        @Override
        public void onCharacteristicChanged(final BluetoothGatt gatt, final BluetoothGattCharacteristic characteristic) {
            super.onCharacteristicChanged(gatt, characteristic);
            if (gatt != null) {
                byte[] datas = characteristic.getValue();
                String message = new String(datas);
                StringBuilder receiveMsg = StringPool.getCurrent().getStringBuilder();

                if (message.contains("{") && !message.contains("}")) {
                    if (receiveMsg != null) {
                        receiveMsg.setLength(0);
                    }
                    assert receiveMsg != null;
                    receiveMsg.append(message);
                } else if (!message.contains("}") && !message.contains("{")) {
                    receiveMsg.append(message);
                } else if (message.contains("}") && !message.contains("{")) {
                    receiveMsg.append(message);
                    if (receiveMsg.indexOf("{") >= 0 && receiveMsg.indexOf("}") >= 0) {
                        sendBroad(AppConstants.MYACTION, "mTxtRead", receiveMsg.toString());
                    }
                    receiveMsg.setLength(0);
                } else if (message.contains("{") && message.contains("}")) {
                    int index = message.indexOf("{");
                    int index1 = message.indexOf("}");
                    if (index < index1) {
                        receiveMsg.append(message);
                        sendBroad(AppConstants.MYACTION, "mTxtRead", message);
                    } else {
                        String s = message.substring(0, index1 + 1);
                        receiveMsg.append(s);
                        sendBroad(AppConstants.MYACTION, "mTxtRead", receiveMsg.toString());
                        receiveMsg.setLength(0);
                        s = message.substring(index1 + 1, message.length());
                        receiveMsg.append(s);
                    }
                }
            }
        }

        @Override
        public void onDescriptorRead(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {
            super.onDescriptorRead(gatt, descriptor, status);
        }

        @Override
        public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {
            super.onDescriptorWrite(gatt, descriptor, status);
        }

        @Override
        public void onReliableWriteCompleted(BluetoothGatt gatt, int status) {
            super.onReliableWriteCompleted(gatt, status);
        }

        @Override
        public void onReadRemoteRssi(BluetoothGatt gatt, int rssi, int status) {
            super.onReadRemoteRssi(gatt, rssi, status);
        }

        @Override
        public void onMtuChanged(BluetoothGatt gatt, int mtu, int status) {
            super.onMtuChanged(gatt, mtu, status);
        }
    };

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        Log.e(TAG, "开启服务,目标设备" + bluetoothName);
        mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
        if (!mBluetoothAdapter.isEnabled()) {
            mBluetoothAdapter.enable();
        }
        handler = new Handler();
        discoverDevice();
        mSerBroad = new SerBroad();
        initBroad();
        initBuf();
        mBleServerServiceThread = new BleServerServiceThread();
        mBleServerServiceThread.start();
    }

    public void initBuf() {
        gbtBleSendData = ByteTool.setByteArray(gbtBleSendData, (byte) 0);
        btBleSendDataIndexW = 0;
        btBleSendDataIndexR = 0;
        btSendFlag = false;
    }

    public void disconnect() {
        if (mGatt != null) {
            mGatt.disconnect();
        }
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.e(TAG, "服务destroy");
//        mBluetoothAdapter.stopLeScan(mLeScanCallback);
        try {
            unregisterReceiver(mSerBroad);
        } catch (Exception e) {
            e.printStackTrace();
        }
        if (mGatt != null) {
            mGatt.disconnect();
        }
    }

    private void initBroad() {
        IntentFilter filter = new IntentFilter();
        filter.addAction(AppConstants.SERVICE_BROAD_ACTION);
        registerReceiver(mSerBroad, filter);
    }

    public void discoverDevice() {
        handler.postDelayed(new Runnable() {
            @Override
            public void run() {
                mBluetoothAdapter.stopLeScan(mLeScanCallback);
                if (!IsConnected.getCurrent().isHasConnected()) {
                    Log.e(TAG, "单例connect 未连接");
                    sendBroad(AppConstants.MYACTION, "mTxtStatus", "未扫描到设备");
                }
            }
        }, 20000);
        mBluetoothAdapter.startLeScan(mLeScanCallback);
        Log.e(TAG, "开启扫描");
    }

    public void connect(BluetoothDevice device) {
        mGatt = device.connectGatt(this, false, mGattCallback);
        mGatt.connect();
    }

    private void sendBroad(String action, String key, String values) {
        Intent intent = new Intent();
        intent.setAction(action);
        intent.putExtra(key, values);
        sendBroadcast(intent);
    }

    public void BTsendData(String btData) {
        synchronized (this) {
            if (mBleServerServiceThread != null && mBleServerServiceThread.mHandler != null && btData != null && btData.length() > 0) {
                btBleSendDataIndexW = ByteTool.LoopBufferCopyS(gbtBleSendData, btData.getBytes(), btData.getBytes().length, btBleSendDataIndexW, SEND_MAX_BUFFER_SIZE);
                if (!btSendFlag) {
                    mBleServerServiceThread.mHandler.removeMessages(MSG_PERIODFILE_SEND);
                    mBleServerServiceThread.mHandler.sendEmptyMessage(MSG_PERIODFILE_SEND);
                    btSendFlag = true;
                }
            }
        }
    }

    private class SerBroad extends BroadcastReceiver {

        @Override
        public void onReceive(Context context, Intent intent) {
            final String msg = intent.getStringExtra("send");
            if (msg != null) {
                BTsendData(msg);
            }
        }
    }

    public class BleServerServiceThread extends Thread {
        public Handler mHandler = null;

        @SuppressLint("HandlerLeak")
        public void run() {
            Looper.prepare();
            mHandler = new Handler() {
                public void handleMessage(Message msg) {
                    switch (msg.what) {
                        case MSG_PERIODFILE_SEND:
                            int len = ((btBleSendDataIndexW + SEND_MAX_BUFFER_SIZE) - btBleSendDataIndexR) % SEND_MAX_BUFFER_SIZE;
                            if (len != 0) {
                                if (len > 20) len = 20;
                                byte[] DataFrame = new byte[len];
                                btBleSendDataIndexR = ByteTool.LoopBufferCopyR(DataFrame, gbtBleSendData, len, btBleSendDataIndexR, SEND_MAX_BUFFER_SIZE, 0);

                                if (DataFrame.length != 0) {
                                    writeCharacteristic.setValue(DataFrame);
                                    writeCharacteristic.setWriteType(BluetoothGattCharacteristic.WRITE_TYPE_NO_RESPONSE);
                                    mGatt.writeCharacteristic(writeCharacteristic);

                                    mBleServerServiceThread.mHandler.removeMessages(MSG_PERIODFILE_SEND);
                                    mBleServerServiceThread.mHandler.sendEmptyMessageDelayed(MSG_PERIODFILE_SEND, 70);
                                }
                            } else {
                                btSendFlag = false;
                            }
                            break;
                    }
                }
            };

            Looper.loop();
        }

        public void cancel() {
            Log.i(TAG, "Stop looping the child thread's message queue");
            mHandler.getLooper().quit();
        }
    }
}
